import createEle from "./creatEle"
import patchVNode from "./patchVNode"
export default function updateChildren (parentEle, oldChil, newChil) {
    console.log(oldChil, newChil)
    // 旧前
    let oldStartIndex = 0
    // 新前
    let newStartIndex = 0
    // 旧后
    let oldEndIndex = oldChil.length - 1
    // 新后
    let newEndIndex = newChil.length - 1

    let keyMap = null

    // 旧前旧后节点
    let oldStartVnode = oldChil[0]
    let oldEndVnode = oldChil[oldEndIndex]
    let newStartVnode = newChil[0]
    let newEndVnode = newChil[newEndIndex]

    while (oldStartIndex <= oldEndIndex && newStartIndex <= newEndIndex) {
        if (oldStartVnode == null || oldChil[oldStartIndex] == undefined) {
            oldStartIndex = oldChil[++oldStartIndex]
        } else if (oldEndVnode == null || oldChil[oldEndIndex] == undefined) {
            oldEndVnode = oldChil[--oldEndIndex]
        } else if (newStartVnode == null || newChil[newStartIndex] == undefined) {
            newStartVnode = newChil[++newStartIndex]
        } else if (newEndVnode == null || newChil[newEndIndex] == undefined) {
            newEndVnode = newChil[--newEndIndex]
        } else if (checkSameVnode(oldStartVnode, newStartVnode)) {
            // 新前旧前命中
            console.log('1. 新前旧前命中')
            patchVNode(oldStartVnode, newStartVnode)
            oldStartVnode = oldChil[++oldStartIndex]
            newStartVnode = newChil[++newStartIndex]
        } else if (checkSameVnode(oldEndVnode, newEndVnode)) {
            // 新后旧后命中
            console.log('2. 新后旧后命中')
            patchVNode(oldEndVnode, newEndVnode)
            oldStartVnode = oldChil[--oldEndIndex]
            newStartVnode = newChil[--newEndIndex]
        } else if (checkSameVnode(oldStartVnode, newEndVnode)) {
            // 新后旧前命中
            console.log('3. 新后旧前命中')
            patchVNode(oldStartVnode, newEndVnode)
            // 将旧前的节点移动到到旧后的节点后面
            parentEle.insertBefore(oldStartVnode.elm, oldEndVnode.elm.nextSibling)
            oldStartVnode = oldChil[++oldStartIndex]
            newEndVnode = newChil[--newEndIndex]
        } else if (checkSameVnode(oldEndVnode, newStartVnode)) {
            // 新前旧后命中
            console.log('4. 新前旧后命中')
            patchVNode(oldEndVnode, newStartVnode)
            // 将旧后的节点移动到旧前节点前面
            parentEle.insertBefore(oldEndVnode.elm, oldStartVnode.elm)
            oldEndVnode = oldChil[--oldEndIndex]
            newStartVnode = newChil[++newStartIndex]
        } else {
            // 四种方式都没有命中的情况
            console.log('啥子都没命中')
            
            if (!keyMap) {
                keyMap = {}
                for (let i = oldStartIndex; i <= oldEndIndex; i++) {
                    const key = oldChil[i].key
                    if (key != undefined) {
                        keyMap[key] = i
                    }
                }
            }
            // 利用newStartIndex指向的节点的key去与oldDom中是否同时存在
            // 如果存在：需要在lodDom中移动该节点
            // 如果不存在：创建节点，然后插入到oldDom中
            // 新dom继续往下++，匹配下一个节点
            const idxInOld = keyMap[newStartVnode.key]
            if (idxInOld == undefined) {
                parentEle.insertBefore(createEle(newStartVnode), oldStartVnode.elm)
            } else {
                const elmToMove = oldChil[idxInOld]
                patchVNode(elmToMove, newStartVnode)
                oldChil[idxInOld] = undefined
                parentEle.insertBefore(elmToMove.elm, oldStartVnode.elm)
            }
            newStartVnode = newChil[++newStartIndex]
        }
    }
    if (newStartIndex <= newEndIndex) {
        console.log('新DOM中还有未处理的节点')
        for (let i = newStartIndex; i <= newEndIndex; i++) {
            parentEle.insertBefore(createEle(newChil[i]), oldChil[oldStartIndex].elm)
        }
    } else if (oldStartIndex <= oldEndIndex) {
        console.log('旧DOM中还有未处理的节点')
        // 批量删除未处理的节点
        for (let i = oldStartIndex; i <= oldEndIndex; i++) {
            if (oldChil[i]) {
                parentEle.removeChild(oldChil[i].elm)   
            }
        }
    }
}

function checkSameVnode (a, b) {
    return a.sel == b.sel && a.key == b.key
}